package com.pure.common.thread;

/**
 * @description: thread local user
 * @date: 2022-09-09 23:45
 * @since 1.2.0
 **/
public class ThreadLocalUser {
    public static void main(String[] args) {

        // https://github.com/alibaba/transmittable-thread-local
        InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();
        inheritableThreadLocal.set("我是 main 方法");

        new Thread(() -> {

            String name = Thread.currentThread().getName();
            System.out.println("thread name : " + name + ", main thread share value : " + inheritableThreadLocal.get());
        }).start();

        new ProcessOne().process();
    }
}

class ProcessOne {
    public void process() {
        PureUser user = new PureUser("张三");
        UserContextHolder.threadLocalUser.set(user);
        PureUser threadLocalUser = UserContextHolder.threadLocalUser.get();
        System.out.println("ProcessOne.class - 用户名：" + threadLocalUser.getName());
        new ProcessTow().process();
    }
}

class ProcessTow {
    public void process() {
        PureUser pureUser = UserContextHolder.threadLocalUser.get();
        System.out.println("ProcessTow.class - 用户名：" + pureUser.getName());
        new ProcessThree().process();
    }
}

class ProcessThree {
    public void process() {
        PureUser pureUser = UserContextHolder.threadLocalUser.get();
        System.out.println("ProcessThree.class - 用户名：" + pureUser.getName());
        UserContextHolder.threadLocalUser.remove();
    }
}

/**
 * @description: 当前用户信息需要被线程内所有方法共享，解决跨方法参数透传。
 * 1、一个比较繁琐的解决方案是把 user 作为参数层层传递，从 方法1() 传到 方法2()，以此类推，但是这样做会导致代码冗余且不易维护。
 * 2、进阶点就是 userMap 来保存，但是当多线程同时工作时，需要保证线程安全，需要用synchronized，或者 ConcurrentHashMap，但无论用什么，都会对性能有所影响。
 * @date 2022/9/9 11:55 下午
 * @since 1.2.1
 */
class UserContextHolder {
    // 类变量
    public static ThreadLocal<PureUser> threadLocalUser = new ThreadLocal();
}

class PureUser {

    private String Name;

    public PureUser(String name) {
        Name = name;
    }

    public PureUser() {
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }
}
